"use client";

import {useEffect, useRef, useState} from "react";
import {Paper, Group, Box} from "@mantine/core";
import {useFullscreen} from "@mantine/hooks";

import cytoscape, {Core, ElementDefinition} from "cytoscape";
import dagre from "cytoscape-dagre";
import coseBilkent from "cytoscape-cose-bilkent";
import classes from "./IpdGraph.module.css";

import {style, updateEdgeWidthStyle} from "./cy-style";
import {addCyEvents} from "./cy-events";
import {IpdGraphZoom} from "./IpdGraphZoom";
import {IpdGraphLayout} from "./IpdGraphLayout";
import {IpdGraphDownload} from "./IpdGraphDownload";
import {IpdGraphFullscreen} from "./IpdGraphFullScreen";

cytoscape.use(dagre);
cytoscape.use(coseBilkent);

export const IpdGraph = ({elements}: {elements: ElementDefinition[]}) => {
  const cyRef = useRef<HTMLDivElement | null>(null); // Cytoscape 容器
  const cyInstance = useRef<Core | null>(null); // Cytoscape 实例
  const [cyReady, setCyReady] = useState(false); // Cytoscape 完成渲染标志

  const {ref, toggle, fullscreen} = useFullscreen();

  useEffect(() => {
    // 组件挂载时先检查容器是否存在
    if (cyRef.current) {
      // 如果实例不存在，那么需要初始化
      if (!cyInstance.current) {
        cyInstance.current = cytoscape({
          container: cyRef.current,
          layout: {name: "circle"},
          style: style,
          elements,
          zoom: 1,
          wheelSensitivity: 0.1,
        });
        // 计算 bw 的最小值和最大值
        let minBw = Infinity;
        let maxBw = -Infinity;
        cyInstance.current.edges().forEach((edge) => {
          const bw = edge.data("bw");
          minBw = Math.min(minBw, bw);
          maxBw = Math.max(maxBw, bw);
        });

        // 更新边的宽度样式
        updateEdgeWidthStyle(cyInstance.current, minBw, maxBw);

        addCyEvents(cyInstance.current); // 添加事件
        setCyReady(true); // 标记 Cytoscape 初始化完成
        cyInstance.current.resize(); // 强制调整大小
      }
    }
    // 组件卸载时的操作
    return () => {
      cyInstance.current?.destroy();
      cyInstance.current = null;
    };
  }, [elements]); // 表示只在组件挂载和卸载时执行

  return (
    <Box ref={ref} style={{height: fullscreen ? "100vh" : "400px", position: "relative"}}>
      <Paper
        ref={cyRef}
        style={{height: "100%", width: "100%", position: "relative"}}
        className={classes.bgDot}
      />
      {cyReady && cyInstance.current && (
        <Group
          justify="space-between"
          gap="xs"
          style={{
            position: "absolute",
            top: 10,
            right: 10,
          }}
        >
          <>
            <IpdGraphLayout cy={cyInstance.current} />
            <IpdGraphZoom cy={cyInstance.current} />
            <IpdGraphDownload cy={cyInstance.current} />
            <IpdGraphFullscreen fullscreen={fullscreen} toggle={toggle} />
          </>
        </Group>
      )}
    </Box>
  );
};
